package vn.mahjonggame.game.request;


import java.util.Collections;
import java.util.List;

import org.apache.log4j.Logger;

import vn.mahjonggame.game.Mahjong;
import vn.mahjonggame.game.MahjongExtension;
import vn.mahjonggame.metadata.GameActionType;
import vn.mahjonggame.metadata.MatchState;
import vn.mahjonggame.metadata.Player;
import vn.mahjonggame.metadata.PlayerMode;
import vn.mahjonggame.metadata.MObject;
import vn.mahjonggame.metadata.Response;
import vn.mahjonggame.metadata.RoomVarName;
import vn.mahjonggame.metadata.Tile;
import vn.mahjonggame.metadata.TileSet;
import vn.mahjonggame.metadata.UserVarName;
import vn.mahjonggame.platform.GameplayConfig;
import vn.mahjonggame.platform.PlatformClient;
import vn.mahjonggame.platform.PlatformConfig;
import vn.mahjonggame.util.PlayerComparator;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;

public class CallTsumoHandler extends BaseClientRequestHandler {
	
	@Override
	public void handleClientRequest(User user, ISFSObject params){
		MahjongExtension ext = (MahjongExtension) getParentExtension();
		Mahjong mahjong = ext.getMahjong();
		List<Player> players = mahjong.getPlayers();
		Room room = ext.getGameRoom();
		Logger logger = mahjong.getLogger();		
		List<User> users = user.getLastJoinedRoom().getUserList();		
		Player player = mahjong.getPlayerById(user.getId());
		
		player.cancelTimer();
		
		mahjong.calculateFuScore(player);
		mahjong.calculateScore(player);
		
		//mahjong.calculateHanScore(player, tile); //This is calculated at PickTileOnDeathWall
		logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "HAN SCORE: " + player.getHanScore()));
		logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "YAKU: " + player.getYakuList()));
		logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "YAKUMAN: " + player.getYakumanList()));
		logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "OTHER YAKUMAN: " + player.getOtherYakumanList()));
		logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "FU SCORE: " + player.getFuScore()));					
		logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "SCORE: " + player.getScore()));
		
		/*
		 * Calculate the final score 
		 */
		double score = player.getScore();
		
		for(int i = 0; i < players.size(); i++){
			Player playerTmp = players.get(i);
			logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "Calculate final score for : " + playerTmp.toString()));
			logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "finalScore : " + playerTmp.getFinalScore()));
			
			double finalScore = playerTmp.getFinalScore();
			double extendedScore = 0;
			
			if(player.getPlayerPosition() != 0){
				if(playerTmp.equals(player)){
					extendedScore = score * 4;					
				}
				else {					
					if(playerTmp.getPlayerPosition() == 0){
						extendedScore = -(score * 2);						
					}
					else {
						extendedScore = -score;						
					}
				}
			}
			else {
				if(playerTmp.equals(player)){
					extendedScore = score * 6;					
				}
				else {
					extendedScore = - (score * 2);					
				}
			}
			
			extendedScore = Math.round(extendedScore / 100) * 100;
			playerTmp.setExtendedScore(extendedScore);
			
			finalScore = finalScore + extendedScore;
			playerTmp.setFinalScore(finalScore);
			
			logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "extendedScore : " + playerTmp.getExtendedScore()));
			logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "finalScore : " + playerTmp.getFinalScore()));
		}
		
		int roomBet = room.getVariable(RoomVarName.roomBet.toString()).getIntValue();
		
		/*
		 * Call game_finish_game API
		 */
		logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "isHasCalledFinishAPI: " + mahjong.isHasCalledFinishAPI()));
		if(!mahjong.isHasCalledFinishAPI()){
			
			if (ext.getPlayerMode() == PlayerMode.REAL_MODE.ordinal()){
				SFSObject res = mahjong.gameFinishGame(player, GameActionType.callTsumo.toString());				
				if(res != null){
					send(GameActionType.callTsumo.toString(), res, users);
					return;
				}
			}
			
			mahjong.setHasCalledFinishAPI(true);
		}
		/*
		 * End call game_finish_game
		 */
				
		/*
		 * Response
		 */
		Response.Builder response = new Response.Builder();		
		SFSArray sfsPlayerArray = new SFSArray();

		PlayerComparator c = new PlayerComparator();
		
		Collections.sort(players, c);
		
		for(int i = 0; i < players.size(); i++) {
			Player iPlayer = players.get(i);					
			
			User iUser = mahjong.getUserByPlayerId(iPlayer.getPlayerId(), users);
						
			Response.Builder sfsUser = new Response.Builder();
			sfsUser.name(iPlayer.getName())
					.point(iPlayer.getExtendedScore());
			
			if(ext.getPlayerMode() == PlayerMode.REAL_MODE.ordinal() && iUser != null){
				SFSObject res = mahjong.useGetBalance(sfsUser, iUser, iPlayer, GameActionType.callTsumo.toString());
				if(res != null){
					send(GameActionType.callTsumo.toString(), res, users);
					return;
				}
			}
			else{
				double amount = (iPlayer.getExtendedScore() * roomBet) / GameplayConfig.INIT_SCORE;
				sfsUser.money(amount);				
			}			
			
			if(iPlayer.equals(player)){
				sfsUser.isWinner(true);							
			}
			else {
				sfsUser.isWinner(false);							
			}
			
			sfsUser.tiles(mahjong.tileArrayToTileIdArray(iPlayer.getLeftTiles()));					
			logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "Player " + iPlayer.toString() + " " + iPlayer.getLeftTiles()));			
			sfsPlayerArray.addSFSObject(sfsUser.build().getSFSObject());			
		}
		
		Response.Builder object = new Response.Builder();
		object.winPos(player.getPlayerPosition())
				.losePos(player.getPlayerPosition())
				.winTile(-1)
				.loseTile(-1);
		
		response.TSUMO(object.build().getSFSObject())
				.turn(player.getPlayerPosition())
				.players(sfsPlayerArray);
		
		send(GameActionType.callTsumo.toString(), response.build().getSFSObject(), users);				
		ext.addAction(user, GameActionType.callTsumo.toString());			
		ext.setMatchState(MatchState.SHOW_RESULT);
		logger.info(mahjong.log(room, player, GameActionType.callTsumo.toString(), "MatchState: " + ext.getMatchState()));
	}
}
